/*
 * SPDX-License-Identifier: BSD-3-Clause
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved.
 * Description  : udk tailq interface
 */

#ifndef UDK_TAILQ_H
#define UDK_TAILQ_H

#include <sys/queue.h>

#define UDK_TAILQ_NAMESIZE 32

struct udk_tailq_entry {
    TAILQ_ENTRY(udk_tailq_entry) next; /* Pointer entries for a tailq list */
    void *data; /* Pointer to the data referenced by this tailq entry */
};

TAILQ_HEAD(udk_tailq_entry_head, udk_tailq_entry);
/*
 * The structure defining a tailq header entry for storing
 * in the udk_config structure in shared memory. Each tailq
 * is identified by name.
 * Any library storing a set of objects e.g. rings, mempools, hash-tables,
 * is recommended to use an entry here, so as to make it easy for
 * a multi-process app to find already-created elements in shared memory.
 */
struct udk_tailq_head {
    struct udk_tailq_entry_head tailq_head; /* NOTE: must be first element */
    char name[UDK_TAILQ_NAMESIZE];
};

struct udk_tailq_elem {
    /*
     * Reference to head in shared mem, updated at init time by
     * udk_tailqs_init()
     */
    struct udk_tailq_head *head;
    TAILQ_ENTRY(udk_tailq_elem) next;
    const char name[UDK_TAILQ_NAMESIZE];
};

/* Return the first tailq entry cast to the right struct. */
#define UDK_TAILQ_CAST(tailq_entry, struct_name) \
    ((struct struct_name *)&(tailq_entry)->tailq_head)

int udk_tailqs_init(void);
int udk_tailq_register(struct udk_tailq_elem *t);

#define UDK_REGISTER_TAILQ(t) \
UDK_INIT(tailqinitfn_ ##t) \
{ \
    if (udk_tailq_register(&(t)) < 0) \
        udk_panic("Cannot initialize tailq: %s\n", (t).name); \
}

#endif /* UDK_TAILQ_H */
